package com.own.component.security.aspect;

import com.own.aop.permission.PermissionModule;
import com.own.aop.permission.PermissionOperation;
import com.own.aop.permission.PermissionOperations;
import com.own.component.common.exception.BusinessException;
import com.own.component.common.login.util.SessionUserUtil;
import com.own.component.security.condition.MenuAspectCondition;
import com.own.constant.ConstantLogic;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Conditional;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * PermissionOperationAspect
 *
 * @author chenxueli
 * @date 2022-08-09 14:54:00
 */
@Aspect
@Component
@Order(1)
@Conditional(MenuAspectCondition.class)
public class PermissionOperationAspect {

    @Pointcut("@annotation(com.own.aop.permission.PermissionOperation)")
    public void operation() {
    }

    @Pointcut("@annotation(com.own.aop.permission.PermissionOperations)")
    public void operations() {
    }

    @Before("operation() && @annotation(data)")
    public void menuBefore(JoinPoint point, PermissionOperation data) {
        check(getModule(point, data.module()), data.value(), false, data.accountType());
    }

    @Before("operations() && @annotation(array)")
    public void menusBefore(JoinPoint point, PermissionOperations array) {
        switch (array.logic()) {
            case ConstantLogic.AND:
                for (var data : array.value()) {
                    check(getModule(point, data.module()), data.value(), false, data.accountType());
                }
                break;
            case ConstantLogic.OR:
            default:
                // 只要有一个权限是满足的就可以访问
                for (var data : array.value()) {
                    var flag = check(getModule(point, data.module()), data.value(), true, data.accountType());
                    if (flag) {
                        return;
                    }
                }
                throw new BusinessException("没有权限访问");
        }

    }

    /**
     * 获取模块名称信息
     *
     * @param point  切点信息
     * @param module 模块名称
     * @return 模块名称信息
     */
    @SuppressWarnings("unchecked")
    private String getModule(JoinPoint point, String module) {
        if (StringUtils.isBlank(module)) {
            var annotation = (PermissionModule) point.getSignature().getDeclaringType().getAnnotation(PermissionModule.class);
            if (annotation != null) {
                return annotation.value();
            }
        }
        return module;
    }

    /**
     * 判断方法
     *
     * @param module      模块信息
     * @param operation   操作信息
     * @param isReturn    是否返回
     * @param accountType 账号类型 1=普通用户 2=管理员
     */
    private boolean check(String module, String operation, boolean isReturn, int accountType) {
        if (StringUtils.isBlank(module)) {
            throw new BusinessException("未设置模块名称，没有权限访问");
        }
        // 获取当前的登录用户信息
        var permissionUser = SessionUserUtil.getPermissionUser();
        // 判断当前登录用户和所需要账号的类型是否匹配（仅限管理员访问）
        if (permissionUser.accountType() != accountType) {
            throw new BusinessException("没有权限访问");
        }
        // 获取当前用户的当前菜单模块的权限信息
        var flag = permissionUser.checkOperation(module, operation);
        if (flag || isReturn) {
            return flag;
        }
        throw new BusinessException("没有权限访问");
    }

}
